AWS IoT EventsをCloudFormationで作ってみた
はじめに
いままで手動ポチポチでIoT Eventsを作っていました。 動作を試す実験だったので十分でしたが、案件で採用する可能性が高くなったため、IoT EventsをCloudFormationで作ってみました。
おすすめの方
- AWS IoT EventsをCloudFormationで作成したい方
仕様を決める
デバイス
- 水位情報をクラウドに送信する
- デバイスが送信する水位情報は下記とする
- 水位(メートル): waterLevel
- 時刻(ミリ秒): timestamp
{ "waterLevel": 10, "timestamp": 1601258079088 }
トピック
- デバイスは下記トピックにデータを送信する
sample/<デバイスID>/waterLevel
クラウド(IoT Events)
- しきい値は30とする
- しきい値以上になった場合、SNSトピックを発行してメール送信する(水位が異常です)
- しきい値を下回った場合、SNSトピックを発行してメール送信する(復旧しました)
IoT EventsをCloudFormationで作成する
CloudFormationテンプレート
下記を定義しています。
- メール通知用のSNSトピック
- IoTルール
- IoTルール用のIAMロール
- IoT Eventsの入力情報
- IoT Eventsの探知器モデル
- IoT Eventsの探知器モデル用のIAMロール
AWSTemplateFormatVersion: 2010-09-09 Description: IoT Events Sample Resources: WaterLevelNotifyTopic: Type: AWS::SNS::Topic Properties: Subscription: - Endpoint: sample@example.com Protocol: email waterLevelTopicRule: Type: AWS::IoT::TopicRule Properties: RuleName: water_level_topic_rule TopicRulePayload: AwsIotSqlVersion: "2016-03-23" RuleDisabled: false Sql: >- SELECT topic(2) as deviceId, * as payload FROM 'sample/+/waterLevel' Actions: - IotEvents: InputName: !Ref WaterLevelEventsInput RoleArn: !GetAtt WaterLevelTopicRuleRole.Arn WaterLevelTopicRuleRole: Type: AWS::IAM::Role Properties: RoleName: water-level-topic-rule-role AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: iot.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AWSIoTEventsFullAccess WaterLevelEventsInput: Type: AWS::IoTEvents::Input Properties: InputName: WaterLevelInputData InputDefinition: Attributes: - JsonPath: deviceId - JsonPath: payload.waterLevel - JsonPath: payload.timestamp WaterLevelDetectorModel: Type: AWS::IoTEvents::DetectorModel Properties: DetectorModelName: water-level-model Key: deviceId EvaluationMethod: BATCH RoleArn: !GetAtt WaterLevelEventsDetectorModelRole.Arn DetectorModelDefinition: InitialStateName: Normal States: - StateName: Normal OnInput: TransitionEvents: - EventName: to_warning NextState: Warning Condition: $input.WaterLevelInputData.payload.waterLevel >= 30 - StateName: Warning OnEnter: Events: - EventName: send-mail-to-warning Actions: - Sns: TargetArn: !Ref WaterLevelNotifyTopic Payload: Type: STRING ContentExpression: "'水位の上昇を検知しました。対象デバイスID: ${$input.WaterLevelInputData.deviceId}, 水位: ${$input.WaterLevelInputData.payload.waterLevel}'" OnInput: TransitionEvents: - EventName: to_normal NextState: Normal Condition: $input.WaterLevelInputData.payload.waterLevel < 30 OnExit: Events: - EventName: send-mail-to-normal Actions: - Sns: TargetArn: !Ref WaterLevelNotifyTopic Payload: Type: STRING ContentExpression: "'水位が復旧しました。対象デバイスID: ${$input.WaterLevelInputData.deviceId}, 水位: ${$input.WaterLevelInputData.payload.waterLevel}'" WaterLevelEventsDetectorModelRole: Type: AWS::IAM::Role Properties: RoleName: water-level-detector-model-role AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: iotevents.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AWSIoTEventsFullAccess - arn:aws:iam::aws:policy/AmazonSNSFullAccess
デプロイ
aws cloudformation deploy \ --template-file iot_events.yml \ --stack-name IoT-Events-Sample-Stack \ --capabilities CAPABILITY_NAMED_IAM \ --no-fail-on-empty-changeset
デプロイされた探知器モデルを確認する
予定通りにできました。
動作確認
waterLevel=10を送信すると、Normal状態になる
- トピック: sample/d0001/waterLevel
{ "waterLevel": 10, "timestamp": 1601258079088 }
Normal状態になりました。
waterLevel=30を送信すると、Warning状態になってメールが来る
- トピック: sample/d0001/waterLevel
{ "waterLevel": 30, "timestamp": 1601258079088 }
Warning状態になりました。
水位の上昇を知らせるメールも来ています。
waterLevel=29を送信すると、Normal状態になって復旧メールが来る
- トピック: sample/d0001/waterLevel
{ "waterLevel": 29, "timestamp": 1601258079088 }
Normal状態になりました。
復旧メールも来ています。
さいごに
いろんなところでハマりました。最初からCloudFormationで作るのは大変なので、手動で作成してからエクスポートを行い、その内容を参考にすると便利でした。どなたかの参考になれば幸いです。